/**
*  \file paragen.c
*
*  \brief   Parameter Generator
*
*  \author  Michael J. Hohmann <michael.hohmann@linde-mh.de>
*  \author  Joerg.Treisch      <joerg.treisch@linde-mh.de>
*
*/

/*===============================================[ private includes  ]================================================*/
#include "paragen.h"
#include "../cfg/paragen_cfg.h"
#include "../pal/pal_mem.h"

/*===============================================[ private defines   ]================================================*/
#define PARAGEN_VALID_VALUE               U32_CONST( 0xCAFEBABE )
#define PARAGEN_INVALID_VALUE             U32_CONST( 0xBADC0DE  )
#define PARAGEN_CHECKSUMM_START_VALUE     U32_CONST( 0xFFFFFFFF )

/*===============================================[ private datatypes ]================================================*/
typedef RC (*paragen_shift_function_t)( struct paragen_type_header const  * i, void * item, S16 dir );

/*===============================================[ private variables ]================================================*/

/*===============================================[ public variables  ]================================================*/

/*===============================================[ private functions ]================================================*/
STATIC_INLINE BO paragen_check_param_type_u8_mm ( struct paragen_type_u8_mm  const *p, void const * data, pal_size_t len );
STATIC_INLINE BO paragen_check_param_type_u16_mm( struct paragen_type_u16_mm const *p, void const * data, pal_size_t len );
STATIC_INLINE BO paragen_check_param_type_u32_mm( struct paragen_type_u32_mm const *p, void const * data, pal_size_t len );
STATIC_INLINE BO paragen_check_param_type_s8_mm ( struct paragen_type_s8_mm  const *p, void const * data, pal_size_t len );
STATIC_INLINE BO paragen_check_param_type_s16_mm( struct paragen_type_s16_mm const *p, void const * data, pal_size_t len );
STATIC_INLINE BO paragen_check_param_type_s32_mm( struct paragen_type_s32_mm const *p, void const * data, pal_size_t len );
STATIC_INLINE BO paragen_check_param_type_ch_mm ( struct paragen_type_ch_mm  const *p, void const * data, pal_size_t len );
#ifdef CC_PARAGEN_USE_F32
STATIC_INLINE BO paragen_check_param_type_f32_mm( struct paragen_type_f32_mm const *p, void const * data, pal_size_t len );
#endif

STATIC_INLINE RC paragen_shift_param_type_u8 ( struct paragen_type_header const * info, void * item, S16 dir );
STATIC_INLINE RC paragen_shift_param_type_u16( struct paragen_type_header const * info, void * item, S16 dir );
STATIC_INLINE RC paragen_shift_param_type_u32( struct paragen_type_header const * info, void * item, S16 dir );
STATIC_INLINE RC paragen_shift_param_type_s8 ( struct paragen_type_header const * info, void * item, S16 dir );
STATIC_INLINE RC paragen_shift_param_type_s16( struct paragen_type_header const * info, void * item, S16 dir );
STATIC_INLINE RC paragen_shift_param_type_s32( struct paragen_type_header const * info, void * item, S16 dir );
#ifdef CC_PARAGEN_USE_F32
STATIC_INLINE RC paragen_shift_param_type_f32( struct paragen_type_header const * info, void * item, S16 dir );
#endif

static U32 paragen_checksum(U32 start_value, void * data, U32 size );
static paragen_shift_function_t paragen_get_shift_function(enum paragen_type type);
static U32 paragen_get_size( struct paragen_type_header const *p );
static BO paragen_check_all_param( struct paragen_object const * const obj );
static BO paragen_check_param( struct paragen_type_header const *p, void const * data, pal_size_t len );
STATIC_INLINE struct paragen_index const  * paragen_lookup( struct paragen_object const * const obj, U32 index );
static int paragen_compare(const void * keyval, const void * datum);

/*====================================================================================================================*/

RC paragen_get( struct paragen_object const  * const obj, U32 index, void  *data, U32 *size , U32 readlevel )
{
   ASSERTOR_PRE( NIL != obj, "NIL is not acceptable as obj pointer");
   ASSERTOR_PRE( NIL != data,"NIL is not acceptable as data pointer");
   ASSERTOR_PRE( NIL != size,"NIL is not acceptable as size pointer");
   {
      RC  rv           = RC_SUCCESS;

      /* try to find a valid entry in the object list */
      struct paragen_index const  *index_obj = paragen_lookup( obj, index);
      if( NIL == index_obj)
      {
         rv = RC_ERROR_OPEN;
      }
      else
      {
         /* yes, some valid information avaiable */
         struct paragen_type_header const * type_obj = index_obj->info;

         U32 current_size = paragen_get_size( type_obj );

         /* check if access to parameter is allowed */
         if( type_obj->readlevel & readlevel )
         {
           /* copy data to ram */
            pal_memcpy( data, ( U8*)obj->ram_param + type_obj->offset, (pal_size_t) current_size );
         }
         else
         {
            rv = RC_ERROR_INVALID;
         }
         *size=current_size;
      }
      return rv;
   }
}


RC paragen_set( struct paragen_object const * const obj, U32 index, void const * data, U8 size, U32  writelevel )
{
   RC rv = RC_SUCCESS;

   /* try to find a valid entry in the object list */
   struct paragen_index const    *index_obj = paragen_lookup( obj, index);

   if( NIL == index_obj)
   {
      rv = RC_ERROR_OPEN;
   }
   else
   {
      struct paragen_type_header const * p   = index_obj->info;

      /* check if access to parameter is allowed */
      //if( p->writelevel & writelevel )
      if( p->writelevel <= writelevel )
      {
         /* check if parameter limits are ok */
         if( FALSE != paragen_check_param( p, data, size) )
         {
            /* copy data to ram */
            pal_memcpy( ((U8*)obj->ram_param) + p->offset, data, size);
            /* store data here */
            rv = paragen_store_by_header(obj, p);
         }
         else
         {
           rv = RC_ERROR_RANGE; /* limits */
         }
      }
      else
      {
            rv = RC_ERROR_FILE_ACCESS; /* wrong access rights */
      }
   }
   return rv;
}

RC paragen_set_default( struct paragen_object const * const obj, U32 index, void* data, U8 size, U32  writelevel )
{
   RC  rv = RC_SUCCESS;
   struct paragen_index const *index_obj = paragen_lookup( obj, index); /* try to find a valid entry in the object list */

   UNREFERENCED( data );


   if( NIL == index_obj)
   {
      rv = RC_ERROR_OPEN;
   }
   else
   {
      struct paragen_type_header const * p = index_obj->info;

      /* check if access to parameter is allowed */
      if( p->writelevel & writelevel )
      {
         U32 current_size=paragen_get_size( p );

         if( current_size == size ) /* now check buffer size  */
         {  /* copy data to ram */
            pal_memcpy( ( U8*)obj->ram_param + p->offset, obj->default_parameter, size);
         }
         else
         {
            rv = RC_ERROR_RANGE; /* size */
         }
      }
      else
      {
            rv = RC_ERROR_FILE_ACCESS; /* wrong access rights */
      }
   }
   return rv;
}

#if 0
static RC paragen_invalidate_struct( struct paragen_object const * const obj )
{  /* first make structure invalid */

   U32 value = PARAGEN_INVALID_VALUE;
   return sd_write( obj->dev, (sd_address_t)(obj->nv_param+ HAEDER_VALID_OFFSET) , &value , sizeof value );
}

static RC paragen_validate_struct( struct paragen_object const * const obj )
{
   RC rv= RC_SUCCESS;
   if (RC_SUCCESS == rv) /* write identity finger print  */
   {
      rv = sd_write( obj->dev, (sd_address_t)(obj->nv_param+ HAEDER_FINGER_OFFSET) , obj->fingerprint , sizeof obj->fingerprint );
   }

   if (RC_SUCCESS == rv) /* save parameter to storage device  */
   {
      rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_OFFSET), obj->ram_param , obj->parameter_struct_size );
   }

   if (RC_SUCCESS == rv) /* write checksum */
   {
      U32 checksum =  paragen_checksum( PARAGEN_CHECKSUMM_START_VALUE, obj->ram_param, obj->parameter_struct_size ) ;
      rv = sd_write( obj->dev, (sd_address_t)(obj->nv_param+ HAEDER_CHECKSUM_OFFSET), &checksum , sizeof checksum );
   }

   /* make struct valid */
   if (RC_SUCCESS == rv)
   {
      U32 valid = PARAGEN_VALID_VALUE;
      rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_VALID_OFFSET), &valid , sizeof(U32) );
   }
   return rv;
}
#endif

RC paragen_store( struct paragen_object const * const obj)
{
   ASSERTOR_PRE( NIL!= obj,"NIL is not acceptable as obj pointer" );
   {
      RC rv = RC_ERROR;

      if( paragen_check_all_param(obj) )/* first check if parameters are valid */
      {
         rv=RC_SUCCESS; /* we will not write at all */
      }
      
      if (RC_SUCCESS == rv) /* make struct invalid */
      {  /* first make structure invalid */
         U32 value = PARAGEN_INVALID_VALUE;
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param + HAEDER_VALID_OFFSET), &value , sizeof value );
      }

      if (RC_SUCCESS == rv) /* write identity finger print  */
      {
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_FINGER_OFFSET) , obj->fingerprint , sizeof obj->fingerprint );
      }

      if (RC_SUCCESS == rv) /* save parameter to storage device  */
      {
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_OFFSET), obj->ram_param , obj->parameter_struct_size );
      }

      if (RC_SUCCESS == rv) /* write checksum */
      {
         U32 checksum =  paragen_checksum( PARAGEN_CHECKSUMM_START_VALUE, obj->ram_param, obj->parameter_struct_size ) ;
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_CHECKSUM_OFFSET), &checksum , sizeof checksum );
      }

      /* make struct valid */
      if (RC_SUCCESS == rv)
      {
         U32 valid = PARAGEN_VALID_VALUE;
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_VALID_OFFSET), &valid , sizeof(valid) );
      }
      return rv;
   }
}

RC paragen_store_by_header( struct paragen_object const * const obj, struct paragen_type_header const * p)
{
   ASSERTOR_PRE( NIL!= obj,"NIL is not acceptable as obj pointer" );
   {
      RC rv = RC_ERROR;


      U32 value = PARAGEN_INVALID_VALUE;
      rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param + HAEDER_VALID_OFFSET), &value , sizeof value );

      if (RC_SUCCESS == rv) /* save parameter to storage device  */
      {
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_OFFSET + p->offset), (obj->ram_param + p->offset), paragen_get_size(p) );
      }

      if (RC_SUCCESS == rv) /* write checksum */
      {
         U32 checksum =  paragen_checksum( PARAGEN_CHECKSUMM_START_VALUE, obj->ram_param, obj->parameter_struct_size ) ;
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_CHECKSUM_OFFSET), &checksum , sizeof checksum );
      }

      /* make struct valid */
      if (RC_SUCCESS == rv)
      {
         U32 valid = PARAGEN_VALID_VALUE;
         rv = sd_write( obj->dev, (sd_address_t) (obj->nv_param+ HAEDER_VALID_OFFSET), &valid , sizeof(valid) );
      }
      return rv;
   }
}

RC paragen_load( struct paragen_object const  * const obj )
{
   ASSERTOR_PRE( NIL != obj," NIL not allowed as object pointer.");
   ASSERTOR_PRE( NIL != obj->dev," NIL not allowed as storage device.");
   /* add asserts for all elements in the object */
   {
      RC  rv = RC_ERROR;
      struct paragen_validation_header validation;
      U32 checksum = 0;

      /** read cks and fingerprint */
      sd_read( obj->dev, &validation,      (sd_address_t) (obj->nv_param+ HAEDER_VALID_OFFSET), sizeof validation );


      /** read parameter */
      sd_read( obj->dev, obj->ram_param, (sd_address_t) (obj->nv_param+ HAEDER_OFFSET),  obj->parameter_struct_size );

      /** calculate checksum */
      checksum = paragen_checksum( PARAGEN_CHECKSUMM_START_VALUE, obj->ram_param, obj->parameter_struct_size );

      /* compare fingerprint */
      if( 0== pal_memcmp( obj->fingerprint, validation.fingerprint, sizeof validation.fingerprint )  )
      {
         /* validate checksum */
         if( checksum== validation.checksum )
         {
            if( paragen_check_all_param(obj) )
            {
               rv = RC_SUCCESS; /* everything ok */
            }
            else
            {
               rv= RC_ERROR;
            }

         }
         else
         {
            rv = RC_ERROR_CHECKSUM;
         }
      }
      else
      {
        /* validate checksum */
        if( (checksum== validation.checksum ) && (validation.valid == PARAGEN_INVALID_VALUE))
        {
            U32 count=obj->parameter_total_count;
            struct paragen_index const * index_obj=obj->index_list;
            U32 i = 0;
            for( i = 0; i < count; i++)
            {
                if( paragen_check_param( index_obj->info, (( U8*)obj->ram_param) + index_obj->info->offset, paragen_get_size(index_obj->info) ) == FALSE) // new parameter
                {
                    pal_memcpy( (( U8*)obj->ram_param) + index_obj->info->offset, obj->default_parameter + index_obj->info->offset, paragen_get_size(index_obj->info)  );
                }
                index_obj++;
            }
            paragen_store(obj);

            rv = RC_SUCCESS; /* everything ok */
        }
        else
        {
            rv = RC_ERROR_CHECKSUM;
        }
      }

      if (RC_SUCCESS != rv)
      {
         /* something wrong with the data load default values */
         pal_memcpy( obj->ram_param, obj->default_parameter, (pal_size_t) obj->parameter_struct_size  ); 
         paragen_store(obj);
      }
      return rv;
   }
}

RC paragen_shift(struct paragen_object const  * const obj, U32 index , S16 dir, U32 writelevel )
{
   RC rv=RC_SUCCESS;

        /* try to find a valid entry in the object list */
   struct paragen_index const  * index_obj = paragen_lookup( obj, index);

   if (NIL==index_obj)
   {
      rv=RC_ERROR_OPEN;
   }
   else
   {
      struct paragen_type_header const  * p = index_obj->info;

      if( p->writelevel & writelevel ) /* check if accesslevel allow operation */
      {
         /* call corresponding macro depending on type and shift RAM variable*/
         paragen_shift_function_t func=paragen_get_shift_function( p->type );
         if( func )
         {
            rv = func( p, (U8 *) obj->ram_param + p->offset, dir );
         }
         else
         {
            rv = RC_ERROR;
         }
      }
      else
      {
         rv=RC_ERROR_INVALID;
      }
   }
   return rv;
}

/*===================================================================================================================*/

/** paragen_get_size
*
*   get byte size of parameter
*
*  \param type
*
*  \param info
*
*  \return corresponding byte size or 0 if unknown type
*/
static U32 paragen_get_size( struct paragen_type_header const *p )
{
   switch(p->type)
   {
      case paragen_type_u8_mm:  return 1;
      case paragen_type_u16_mm: return 2;
      case paragen_type_u32_mm: return 4;
      case paragen_type_s8_mm:  return 1;
      case paragen_type_s16_mm: return 2;
      case paragen_type_s32_mm: return 4;
      case paragen_type_ch_mm:
        {
            struct paragen_type_ch_mm const *px = (void *)p;
            return px->min_value;
        }
#ifdef PARAGEN_USE_F32
      case paragen_type_f32_mm: return 4;
#endif
      default: return 0;
   }
}


/** paragen_compare
*
*   compares two elements from an setup object (ROM,RAM and EEPROM values)
*
*  \param keyval  pointer to the object that serves as key for the search, type-casted as a void*.
*  \param datum   pointer to the object that serves as next value near to key in the search, type-casted as a void*.
*
*  \return lower (-1), higher (1) or found (0)
*/
static int paragen_compare(const void * keyval, const void * datum)
{
   U32 index=0;
   struct paragen_index const  *item=datum;
   pal_memcpy(&index,keyval,sizeof index );

   if( index > item->index )
   {
      return 1;
   }

   if( index< item->index )
   {
      return -1;
   }

   return 0;
}

/** paragen_compare_mon
*
*   compares two elements from an monitoring object (only RAM values)
*
*  \param keyval  pointer to the object that serves as key for the search, type-casted as a void*.
*  \param datum   pointer to the object that serves as next value near to key in the search, type-casted as a void*.
*
*  \return lower (-1), higher (1) or found (0)
*/

/** binarysearch():
*
*   searches an array of nitems objects, the initial member of which is pointed to by base, for a member that matches the object pointed to, by key.
*   The size of each member of the array is specified by size.
*   NOTE: The contents of the array should be in ascending sorted order according to the comparison function referenced by compare.
*
*  \param key     This is the pointer to the object that serves as key for the search, type-casted as a void*.
*  \param base    This is the pointer to the first object of the array where the search is performed, type-casted as a void*
*  \param nitem   This is the number of elements in the array pointed by base
*  \param size    This is the size in bytes of each element in the array
*  \param compare This is the function that compares two elements
*
*  \return Pointer to info struct entry or NIL if no entry for this key
*
*/
const void * binarysearch( const void  * key, const void * base, pal_size_t nitem , pal_size_t size,
                                     int (* compare)( const void *, const void * ))
{
   pal_size_t start = 0;
   pal_size_t end = nitem ;
   int result;

   while (start < end)
   {
      pal_size_t mid = start + (end - start) / 2;
      const void * local = (const void  *)((const char  *) base + mid * size);
      result = compare(key, local );
      if (result < 0)
      {
         end = mid;
      }
      else if (result > 0)
      {
         start = mid + 1;
      }
      else
      {
         return (const void  *)((const char  *) base + mid * size);
      }
   }
   return  NIL;
}


/** Find index in paragen_index structure.
*
*  \param obj
*  \param index
*
*  \return Pointer to info struct entry or NIL if
*/
STATIC_INLINE struct paragen_index const  * paragen_lookup( struct paragen_object const * const obj, U32 index )
{
   return (struct paragen_index const   *) binarysearch(&index, obj->index_list, (pal_size_t) obj->parameter_total_count, (pal_size_t)sizeof( struct paragen_index ),  paragen_compare );
}

/** paragen_check_param
*
*   check incoming data against min/max limits
*
*  \param p     pointer to type struct
*  \param data  pointer to data buffer to be checked
*
*  \return TRUE if check is ok
*/

static BO paragen_check_param( struct paragen_type_header const *p, void const * data, pal_size_t len )
{
   switch( p->type )
   {
      case paragen_type_u8_mm:  return paragen_check_param_type_u8_mm ( (void *)p, data, len );
      case paragen_type_u16_mm: return paragen_check_param_type_u16_mm( (void *)p, data, len );
      case paragen_type_u32_mm: return paragen_check_param_type_u32_mm( (void *)p, data, len );
      case paragen_type_s8_mm:  return paragen_check_param_type_s8_mm ( (void *)p, data, len );
      case paragen_type_s16_mm: return paragen_check_param_type_s16_mm( (void *)p, data, len );
      case paragen_type_s32_mm: return paragen_check_param_type_s32_mm( (void *)p, data, len );
      case paragen_type_ch_mm:  return paragen_check_param_type_ch_mm ( (void *)p, data, len );
#ifdef PARAGEN_USE_F32
      case paragen_type_f32_mm: return paragen_check_param_type_f32_mm( (void *)p, data );
#endif
      default: return FALSE;
   }
}

/** paragen_get_shift_function
*
*   shift parameter (inc/dec)
*
*  \param type
*
*  \return corresponding function pointer or NIL if failed
*/

static paragen_shift_function_t paragen_get_shift_function(enum paragen_type type)
{
   switch( type )
   {
      case paragen_type_u8_mm:  return paragen_shift_param_type_u8;
      case paragen_type_u16_mm: return paragen_shift_param_type_u16;
      case paragen_type_u32_mm: return paragen_shift_param_type_u32;
      case paragen_type_s8_mm:  return paragen_shift_param_type_s8;
      case paragen_type_s16_mm: return paragen_shift_param_type_s16;
      case paragen_type_s32_mm: return paragen_shift_param_type_s32;
#ifdef PARAGEN_USE_F32
      case paragen_type_f32_mm: return paragen_shift_param_type_f32;
#endif
      default: return NIL;
   }
}

/** paragen_check_all_param
*
*   check all parameters of an object against min/max limit
*
*  \param obj
*
*  \return TRUE if the object is ok
*/

static BO paragen_check_all_param( struct paragen_object const  * const obj)
{
   U32 count=obj->parameter_total_count;
   struct paragen_index const * index_obj=obj->index_list;

   while( count--)
   {
      if( paragen_check_param( index_obj->info, (( U8*)obj->ram_param) + index_obj->info->offset, paragen_get_size(index_obj->info) ) )
      {
         index_obj++;
      }
      else
      {
         return FALSE;
      }
   }
   return TRUE;
}

/** paragen_checksum
*
*   checksum validation function is called
*
*  \param start_value for CRC
*  \param data        pointer to data buffer
*  \param size        of data in bytes

*
*  \return calculated CRC value for data
*/

static U32 paragen_checksum(U32 start_value, void * data, U32 size )
{
   return paragen_checksum_function( start_value, data, size );
}

/** paragen_shift_function
*
*   macro for different functions, which are type depending
*   in princple: parameter inc/dec
*
*  \param i     pointer to info struct
*  \param item  pointer to item struct
*  \param dir   direction of shift (inc/dec)
*
*  \return RC_SUCCESS
*/
#define paragen_shift_function( functionname, type , sname )                           \
STATIC_INLINE RC functionname( struct paragen_type_header const * i, void  * item, S16 dir )  \
{                                                                                      \
    type  *pvalue = (type *)item;                                                      \
    type value   = *pvalue;                                                            \
   struct sname  *info=(struct sname *)i;                                              \
                                                                                       \
   type iggy = (type)dir *(type)info->increment;                                       \
   value+=iggy;                                                                        \
                                                                                       \
   if( 0 < dir )                                                                       \
   {                                                                                   \
       if(( value > info->max_value )||(value<*pvalue))                                \
       {                                                                               \
          *pvalue = info->max_value;                                                   \
       }                                                                               \
       else                                                                            \
       {                                                                               \
          *pvalue = value;                                                             \
       }                                                                               \
   }                                                                                   \
   else                                                                                \
   {                                                                                   \
       if(( value < info->min_value )||(value>*pvalue))                                \
       {                                                                               \
          *pvalue = info->min_value;                                                   \
       }                                                                               \
       else                                                                            \
       {                                                                               \
          *pvalue = value;                                                             \
       }                                                                               \
   }                                                                                   \
                                                                                       \
   return RC_SUCCESS;                                                                  \
}

paragen_shift_function( paragen_shift_param_type_u8 ,  U8  , paragen_type_u8_mm  )
paragen_shift_function( paragen_shift_param_type_u16,  U16 , paragen_type_u16_mm )
paragen_shift_function( paragen_shift_param_type_u32,  U32 , paragen_type_u32_mm )
paragen_shift_function( paragen_shift_param_type_s8 ,  S8  , paragen_type_s8_mm  )
paragen_shift_function( paragen_shift_param_type_s16,  S16 , paragen_type_s16_mm )
paragen_shift_function( paragen_shift_param_type_s32,  S32 , paragen_type_s32_mm )
#ifdef PARAGEN_USE_F32
paragen_shift_function( paragen_shift_param_type_f32,  F32 , paragen_type_f32_mm )
#endif


/** paragen_check_param_type_xx_mm
*
*
*   check incoming data against min/max limits
*
*  \param p     pointer to type struct
*  \param data  pointer to data buffer to be checked
*
*  \return TRUE if check is ok
*/

STATIC_INLINE BO paragen_check_param_type_u8_mm( struct paragen_type_u8_mm const *p, void const * data, pal_size_t len )
{
   U8 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}

STATIC_INLINE BO paragen_check_param_type_u16_mm( struct paragen_type_u16_mm const *p, void const * data, pal_size_t len )
{
   U16 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}

STATIC_INLINE BO paragen_check_param_type_u32_mm( struct paragen_type_u32_mm const *p, void const * data, pal_size_t len )
{
   U32 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}

STATIC_INLINE BO paragen_check_param_type_s8_mm( struct paragen_type_s8_mm const *p, void const * data, pal_size_t len )
{
   S8 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}

STATIC_INLINE BO paragen_check_param_type_s16_mm( struct paragen_type_s16_mm const *p, void const * data, pal_size_t len )
{
   S16 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}

STATIC_INLINE BO paragen_check_param_type_s32_mm( struct paragen_type_s32_mm const *p, void const * data, pal_size_t len )
{
   S32 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}


STATIC_INLINE BO paragen_check_param_type_ch_mm( struct paragen_type_ch_mm const *p, void const * data, pal_size_t len )
{
   UNREFERENCED( data );
   /* only check length of string */
   return  (len <= p->max_value) && (len >=p->min_value) ;
}

#ifdef PARAGEN_USE_F32
STATIC_INLINE BO paragen_check_param_type_f32_mm( struct paragen_type_f32_mm const *p, void const * data, pal_size_t len )
{
   F32 value=0;
   pal_memcpy( &value, data, sizeof value  );
   return ( (value <= p->max_value) && (value >=p->min_value) && (len == sizeof value ) );
}
#endif
/***********************************************************************************************************************
*                             Copyright 2012 Linde Material Handling. All rights reserved.                             *
***********************************************************************************************************************/
